/* This source file is part of the Delectable Engine.
 * For the latest info, please visit http://delectable.googlecode.com/
 *
 * Copyright (c) 2009-2010 Ryan Chew
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file KeyboardManager.cpp
 * @brief Keyboard manager component.
 */

// Delectable Headers //
#include "dbl/Input/MouseManager.h"
#include "dbl/Core/GameWindow.h"

// Chewable Headers //
#include <cbl/Debug/Assert.h>
#include <cbl/Debug/Logging.h>
#include <cbl/Core/Game.h>

using namespace dbl;

MouseManager::MouseManager( cbl::Game & game )
: cbl::GameComponent( game )
, mWindow( NULL )
, mCurrentX( 0 )
, mCurrentY( 0 )
{
}

MouseManager::~MouseManager()
{
}


void MouseManager::Initialise( void )
{
	mWindow = this->Game.Services.Get< GameWindow >();
	CBL_ASSERT_TRUE( mWindow );
	
	GLOG( "Initialising mouse manager." );

	mWindow->OnWindowMouseMove	+= *this;
	mWindow->OnWindowMouseDown	+= *this;
	mWindow->OnWindowMouseUp	+= *this;
	mWindow->OnWindowMouseWheel	+= *this;
	mWindow->OnWindowMouseLeave	+= *this;
}

void MouseManager::Shutdown( void )
{
	if( !mWindow )
		return;

	GLOG( "Shutting down mouse manager." );

	mWindow->OnWindowMouseMove	-= *this;
	mWindow->OnWindowMouseDown	-= *this;
	mWindow->OnWindowMouseUp	-= *this;
	mWindow->OnWindowMouseWheel	-= *this;
	mWindow->OnWindowMouseLeave	-= *this;

	mWindow = NULL;
}

void MouseManager::Update( cbl::GameTime const & )
{
	for( cbl::Uint32 count = 0; count < Mouse::Count; ++count )
	{
		if( mButtons[ count ] )
			OnMouseDown( E::OnMouseDown::ArgType( Mouse::Button( count ), mCurrentX, mCurrentY ) );
	}
}

DEF_EVENT_HANDLER( MouseManager, E::OnWindowMouseMove )
{
	mCurrentX = args.X;
	mCurrentY = args.Y;

	OnMouseMove( E::OnMouseMove::ArgType( args.X, args.Y ) );
	for( cbl::Uint32 count = 0; count < Mouse::Count; ++count )
	{
		if( mButtons[ count ] )
			OnMouseDrag( E::OnMouseDrag::ArgType( Mouse::Button( count ), args.X, args.Y ) );
	}
}

DEF_EVENT_HANDLER( MouseManager, E::OnWindowMouseDown )
{
	mButtons[ args.Button ] = true;
	OnMouseClick( E::OnMouseClick::ArgType( args.Button, args.X, args.Y ) );
}

DEF_EVENT_HANDLER( MouseManager, E::OnWindowMouseUp )
{
	if( !mButtons[ args.Button ] )
		return;

	mButtons[ args.Button ] = false;
	OnMouseUp( E::OnMouseUp::ArgType( args.Button, args.X, args.Y ) );
}

DEF_EVENT_HANDLER( MouseManager, E::OnWindowMouseWheel )
{
	OnMouseWheel( E::OnMouseWheel::ArgType( args.Delta ) );
}

DEF_EVENT_HANDLER_NA( MouseManager, E::OnWindowMouseLeave )
{
	for( cbl::Uint32 count = 0; count < Mouse::Count; ++count )
	{
		if( !mButtons[ count ] )
			continue;

		mButtons[ count ] = false;
		OnMouseUp( E::OnMouseUp::ArgType( Mouse::Button( count ), mCurrentX, mCurrentY ) );
	}
}
